/*
 * Copyright (C) 2019
 * <tang-haifeng@foxmail.com> <pengren.mcu@qq.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 *
 */

#include <common.h>
#include <clk.h>
#include <led.h>
#include <pwm.h>
#include <pci.h>
#include <scsi.h>
#include <ahci.h>

#include <asm/io.h>
#include <asm/gpio.h>

#include <mach/ls3x.h>
#include <mach/ls7a.h>

DECLARE_GLOBAL_DATA_PTR;

#if defined(CONFIG_LOONGSON_GMAC) || defined(CONFIG_ETH_DESIGNWARE)
void ls7a_set_gmac(void)
{
	u32 val = 0;
	void __iomem *func_config = ioremap(LS7A_FUNC_CONFIG1, 1);

	val = readl(func_config);
	//uncache加速使能，时钟使能
	val = val | (1<<26) | (1<<7) | (1<<5);
	//关闭硬件流控
	val = val & (~(1<<6)) & (~(1<<4));
	writel(val, func_config);
}
#endif

static void save_ddr_param(void)
{
	char cmd[256];
	int i, need_update = 0;
	int node_num = 1;
	unsigned char *dimm_addr = (unsigned char *)DIMM_INFO_IN_SDRAM_OFFS;

	for (i = 0; i < node_num * 2; i++) {
        if (*(dimm_addr + i * MC_INFO_SIZE + DIMM_OFFS_SLOT0_SPD) ||
			*(dimm_addr + i * MC_INFO_SIZE + DIMM_OFFS_SLOT1_SPD)) {
			need_update = 1;
		}
	}

	if (need_update) {
		printf("%s\r\n", __func__);
		run_command("sf probe", 0);
		sprintf(cmd, "sf erase ddr_param 0x%x", 0x00010000);
		run_command(cmd, 0);
		sprintf(cmd, "sf write 0x%p ddr_param 0x%x", (unsigned char *)DIMM_INFO_IN_SDRAM_OFFS, node_num * DIMM_INFO_SIZE);
		run_command(cmd, 0);
	}
}

int board_early_init_f(void)
{
#if defined(CONFIG_LOONGSON_GMAC) || defined(CONFIG_ETH_DESIGNWARE)
	ls7a_set_gmac();
#endif
	return 0;
}

int ls3x_board_late_init(void)
{
#ifdef BEEP_GPIO
	{
	int ret;
	ret = gpio_request(BEEP_GPIO, "beep");
	if (ret == 0) {
		int i;
		for (i=0; i<500; i++) {
			gpio_direction_output(BEEP_GPIO, i & 0x1);
			udelay(220);
		}
		gpio_direction_output(BEEP_GPIO, 1);
	}
	}
#endif

#ifdef CONFIG_PWM_LOONGSON
#ifndef CONFIG_DM_PWM
	pwm_init(0, 0, 1);
	pwm_config(0, 100000, 7812500);
	pwm_enable(0);

	pwm_init(1, 0, 1);
	pwm_config(1, 100000, 7812500);
	pwm_enable(1);

	pwm_init(2, 0, 1);
	pwm_config(2, 100000, 7812500);
	pwm_enable(2);

	pwm_init(3, 0, 1);
	pwm_config(3, 100000, 7812500);
	pwm_enable(3);
#endif
#endif

	save_ddr_param();

	return 0;
}

#ifndef CONFIG_DM_ETH
#if defined(CONFIG_LOONGSON_GMAC) || defined(CONFIG_ETH_DESIGNWARE)
#include <miiphy.h>

extern int gmac_initialize(ulong base_addr, u32 interface);

int board_eth_init(bd_t *bis)
{
	pci_dev_t busdevfunc;
	void *gmac_base;
	int i, ret = -1;

	for (i=0; i<2; i++) {
		busdevfunc = pci_find_device(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_GMAC, i); /* get PCI Device ID */
		if (busdevfunc == -1) {
			printf("Gmac Controller (%04X,%04X) not found\n", PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_GMAC);
			continue;
		}
		gmac_base = pci_map_bar(busdevfunc, PCI_BASE_ADDRESS_0, PCI_REGION_MEM);
		ret = gmac_initialize((ulong)gmac_base, PHY_INTERFACE_MODE_MII);
		if (ret) {
			printf("Gmac Controller (%04X,%04X) %p initialize fail\n", PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_GMAC, gmac_base);
			continue;
		}
	}
	return ret;
}
#endif
#endif
